﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

namespace SlideShowGenerator.Data
{
    /// <summary>  </summary>
    public class SSGenerator
    {
        #region Types Used Here

        /// <summary>  </summary>
        public class SSGenMessageEventArgs : EventArgs
        {
            /// <summary>  </summary>
            public string Message { get; set; }

            /// <summary>  </summary>
            public SSGenMessageEventArgs(string message)
            {
                this.Message = message;
            }
        }

        /// <summary>  </summary>
        public delegate void SSGeneratorMessageHandler(object sender, SSGenMessageEventArgs e);

        #endregion

        #region Instance Variables and Constructor

        private DirectoryInfo path;
        private List<AlbumData> albums = new List<AlbumData>();

        /// <summary>  </summary>
        public SSGenerator(DirectoryInfo imagesPath)
        {
            this.path = imagesPath;
        }

        #endregion 

        #region Messages

        /// <summary>  </summary>
        public event SSGeneratorMessageHandler Message;

        /// <summary>  </summary>
        protected void OnMessage(string message)
        {
            if (message != null)
            {
                Message(this, new SSGenMessageEventArgs(message));
            }
        }

        #endregion

        /// <summary>  </summary>
        public List<AlbumData> Albums
        {
            get { return albums; }
        }

        private void AssureDir(DirectoryInfo path)
        {
            if (!path.Exists)
            {
                Directory.CreateDirectory(path.FullName);
            }
        }

        /// <summary>
        /// Look around and collect info. (Will generate thumbnail files for UI.)
        /// </summary>
        public void Investigate()
        {
            DirectoryInfo dirInfo = path;
            AssureDir(Config.TempDir);
            bool setAlbumThumb;
            foreach (DirectoryInfo subDir in dirInfo.GetDirectories())
            {                
                AlbumData album = new AlbumData();
                album.Title = subDir.Name;
                album.Description = "(Please Fill In)";
                setAlbumThumb = false;
                OnMessage("Found album:" + album.Title);
                DirectoryInfo albumTempPath = new DirectoryInfo(Path.Combine(Config.TempDir.FullName, album.Title));
                AssureDir(albumTempPath);
                foreach (FileInfo file in subDir.GetFiles("*.jpg"))
                {
                    ImageData imageData = new ImageData(file.FullName);
                    OnMessage("Found image: " + file.FullName);
                    imageData.Album = album;
                    //Make thumb to show in UI (using the orginal uses far too much resources)                    
                    string tempThumbPath = Path.Combine(albumTempPath.FullName, imageData.FileBaseName + "_t.jpg");
                    if (!File.Exists(tempThumbPath))
                    {
                        OnMessage("Creating temp thumbnail: " + imageData.FileBaseName + "_t.jpg");
                        string tempImgPath = Path.Combine(albumTempPath.FullName, imageData.FileBaseName + "_temp.jpg");
                        File.Copy(file.FullName, tempImgPath); //could be currently in use, so copy local
                        ImageResizer.ResizeImage(Path.Combine(albumTempPath.FullName, imageData.FileBaseName + "_t.jpg"), 120, tempImgPath);
                        File.Delete(tempImgPath);
                    }
                    imageData.ThumbFile = tempThumbPath;

                    //Check if we have processes the Album Thumbnail
                    if (imageData.FileBaseName.ToLower().Equals("album"))
                    {
                        album.Description = imageData.Comment;
                        album.ThumbImagePath = tempThumbPath;
                        album.ThumbImage = imageData.FileBaseName + "_t.jpg";
                        setAlbumThumb = true;
                    }
                    else
                    {
                        album.Images.Add(imageData);
                    }
                }
                // Check if there is an album thumbnail - otherwise add the first image in the album as the thumbnail
                if (!setAlbumThumb)
                {
                    // Check the album actually contains at least 1 image
                    if (album.Images.Count > 0)
                    {
                        album.ThumbImagePath = album.Images[0].ThumbFile;
                        album.ThumbImage = album.Images[0].FileBaseName + "_t.jpg";
                        setAlbumThumb = true;
                    }
                }
                albums.Add(album);
            }
        }

        /// <summary>
        /// Create resized versions of the original, both a thumbnail and a web-sized image.
        /// </summary>
        /// <param name="outputPath">Base path for output.</param>
        public void GenerateOutputImages(DirectoryInfo outputPath)
        {
            foreach (AlbumData album in albums)
            {
                if (album.EnableGeneration)
                {
                    DirectoryInfo albumPath = new DirectoryInfo( Path.Combine(outputPath.FullName, "Images\\" + album.Title));
                    AssureDir(albumPath);
                    if (!File.Exists(Path.Combine(albumPath.FullName, album.ThumbImage))
                        && File.Exists(album.ThumbImagePath))
                    {
                        File.Copy(album.ThumbImagePath, Path.Combine(albumPath.FullName, album.ThumbImage));
                    }

                    foreach (ImageData image in album.Images)
                    {
                        if (image.EnableGeneration)
                        {
                            string tempFile = albumPath + image.FileBaseName + "_temp.jpg";
                            File.Copy(image.ImageFile, tempFile);
                            if (File.Exists(image.ThumbFile))
                            {
                                string tOutputPath = Path.Combine(albumPath.FullName, image.FileBaseName + "_t.jpg");
                                OnMessage("Copying thumbnail to output: " + tOutputPath);
                                File.Copy(image.ThumbFile, tOutputPath, true);
                            }
                            else
                            {
                                ImageResizer.ResizeImage(Path.Combine(albumPath.FullName, image.FileBaseName + "_t.jpg"), 120, tempFile);
                            }
                            string sOutputPath = Path.Combine(albumPath.FullName, image.FileBaseName + "_s.jpg");
                            OnMessage("Creating web-sized image file: " + sOutputPath);
                            ImageResizer.ResizeImage(sOutputPath, 800, tempFile);
                            File.Delete(tempFile);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Generate the data.xml file.
        /// </summary>
        /// <param name="outputPath">Where to put it.</param>
        public void Generate(DirectoryInfo outputPath)
        {
            OnMessage("Generating 'Data.xml'");
            //Generate xml data file
            //<?xml version="1.0" encoding="utf-8" ?>
            //<data startalbumindex="1" transition="CrossFadeTransition">
            //    <album title="Heidlberg, Germany" description="Europe 2007 Trip"
            //    image="../Images/Europe2007/Heidlberg/Europe_2_109_a.jpg">
            //        <slide title="Square on the way to the castle" description="Photo taken by Ben Hoffman"
            //            image="../Images/Europe2007/Heidlberg/HPIM1170_s.jpg"
            //            thumbnail="../Images/Europe2007/Heidlberg/HPIM1170_t.jpg" />
            //    </albums>
            //</data>
            using (FileStream dataFile = new FileStream(outputPath + "\\Data.xml", FileMode.Create))
            {
                XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
                xmlWriterSettings.Indent = true;
                using (XmlWriter xmlWriter = XmlWriter.Create(dataFile, xmlWriterSettings))
                {
                    xmlWriter.WriteStartElement("data");
                    xmlWriter.WriteAttributeString("startalbumindex", "0");
                    xmlWriter.WriteAttributeString("transition", "CrossFadeTransition");
                    foreach (AlbumData album in albums)
                    {
                        if (album.EnableGeneration)
                        {
                            xmlWriter.WriteStartElement("album");
                            xmlWriter.WriteAttributeString("title", album.Title);
                            xmlWriter.WriteAttributeString("description", album.Description);
                            xmlWriter.WriteAttributeString("image", "Images/" + album.Title + "/" + album.ThumbImage);
                            foreach (ImageData image in album.Images)
                            {
                                if (image.EnableGeneration)
                                {
                                    xmlWriter.WriteStartElement("slide");
                                    xmlWriter.WriteAttributeString("title", image.Title);
                                    xmlWriter.WriteAttributeString("description", image.Comment + " - Taken: " + image.DateTaken);
                                    xmlWriter.WriteAttributeString("image", "Images/" + album.Title + "/" + image.FileBaseName + "_s.jpg");
                                    xmlWriter.WriteAttributeString("thumbnail", "Images/" + album.Title + "/" + image.FileBaseName + "_t.jpg");
                                    xmlWriter.WriteAttributeString("datetaken", image.DateTaken);
                                    xmlWriter.WriteEndElement();
                                }
                            }
                            xmlWriter.WriteEndElement();
                        }
                    }
                    xmlWriter.WriteEndElement();
                }
            }
            OnMessage("Done");
        }
    }
}
